package capturePacket

import (
	"fmt"
	"log"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"bytes"
	"bufio"
	"net/http"
)

var (
	device       string        = "en0"
	snapshot_len int32         = 65535
	promiscuous  bool          = false
	timeout      time.Duration = -1 * time.Second
	err          error
	handle       *pcap.Handle
)

func Capture() {
	// Open device
	handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

	// Get the next packet
	packet, err := packetSource.NextPacket()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(packet)
}

func CaptureLoop() {
	// Open device
	handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	err = handle.SetBPFFilter("tcp and port 8080")
	if err != nil {
		log.Fatal(err)
	}

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

	for packet := range packetSource.Packets() {

		fmt.Println("====== Packet Layers =======")
		for _, layer := range packet.Layers() {
			fmt.Println(layer.LayerType())
		}
		fmt.Println("============================")
		packet.ApplicationLayer()
		// Get IPv4 layer
		ip4Layer := packet.Layer(layers.LayerTypeIPv4)
		if ip4Layer != nil {
			fmt.Println("IPv4 layer detected.")
			ip, _ := ip4Layer.(*layers.IPv4)
			fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
			fmt.Println("Protocol: ", ip.Protocol)
			fmt.Println()
		} else {
			fmt.Println("No IPv4 layer detected.")
		}

		// Get TCP layer
		tcpLayer := packet.Layer(layers.LayerTypeTCP)
		if tcpLayer != nil {
			fmt.Println("TCP layer detected.")
			tcp, _ := tcpLayer.(*layers.TCP)
			fmt.Println("ACK: ", tcp.ACK)
			fmt.Println("SYN: ", tcp.SYN)
			fmt.Println("Seq: ", tcp.Seq)
			fmt.Println("DstPort: ", tcp.DstPort)
			fmt.Println("SrcPort: ", tcp.SrcPort)
			fmt.Println()
		} else {
			fmt.Println("No TCP layer detected.")
		}
	}
}

func CaptureFilter() {
	handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	// Set filter
	err = handle.SetBPFFilter("tcp and port 8080")
	if err != nil {
		log.Fatal(err)
	}
	//fmt.Println("Only capturing TCP port 8080 packets.")

	// Process packets
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
			tcp, _ := tcpLayer.(*layers.TCP)
			if len(tcp.Payload) != 0 {
				reader := bufio.NewReader(bytes.NewReader(tcp.Payload))
				httpReq, _ := http.ReadRequest(reader)
				//fmt.Println(packet)
				fmt.Println(httpReq)
			}
		}
		//Response(packet)
	}
}

func Response(packet gopacket.Packet) {
	appLayer := packet.ApplicationLayer()

	//if appLayer != nil && strings.Contains(string(appLayer.Payload()), "HTTP") {
	if appLayer != nil {

		payloadReader := bytes.NewReader(appLayer.Payload())
		bufferedPayloadReader := bufio.NewReader(payloadReader)

		request, _ := http.ReadRequest(bufferedPayloadReader)
		response, _ := http.ReadResponse(bufferedPayloadReader, request)
		log.Println(request)
		log.Println(response)
	}
}

func CaptureLoop2() {
	handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

	for packet := range packetSource.Packets() {
		fmt.Println(packet)
	}
}